#ifndef CORE_H
#define CORE_H

#pragma warning(push)
#pragma warning(disable: 4251) // class/struct needs to have dll-interface to be used by clients of class
#pragma warning(disable: 4275) // non dll-interface class used as base for dll-interface class
#pragma warning(disable: 4244) // Conversion from double to float

#define WIN32_LEAN_AND_MEAN

#include <list>
#include <string>
#include <assert.h>
#include <Windows.h>

typedef unsigned int uint;

//
// File item
// Handles files which are in use, and can also reload any files which change on demand.
// 
class iFile {
private:
	static std::list<iFile*> s_OpenFiles;
protected:
	std::string strFilePath;
	FILETIME LastWrite;
public:
	iFile();
	~iFile();

	bool CheckFile();
	virtual bool ReopenFile() = 0;

	std::string GetFilePath();
	void SetFilePath(std::string NewFilePath);

	static void CheckAllFiles();
};

//
// Memory managed object
// This will maintain a list of all memory managed objects
// Any which aren't in use will be removed upon calling CollectGarbage()
//
class iMMObj {
private:
	static std::list<iMMObj*> s_LiveObjects;
	static std::list<iMMObj*> s_DeadObjects;
	int RefCount;
protected:
	iMMObj();
	virtual ~iMMObj();
public:
	void MMObjAddRef();
	void MMObjRelease();
	static void CollectGarbage();
};

//
// Memory Managed Pointer
// Basically a pointer with implicit reference tracking for memory management
// Also called a Smart Pointer
//
template <class t>
class MMPtr {
protected:
	t* obj;
public:
	MMPtr() {
		obj = 0;
	}
	MMPtr(t* o) {
		obj = o;
		obj->MMObjAddRef();
	}
	MMPtr(const MMPtr<t> &p) {
		obj=0;
		*this=p;
	}
	~MMPtr() {
		if(obj)
			obj->MMObjRelease();
	}

	inline MMPtr& operator =(t *o) {
		if(obj)obj->MMObjRelease();
		obj = o;
		if(obj)obj->MMObjAddRef();
		return *this;
	}

	inline MMPtr& operator =(const MMPtr<t> &p) {
		if(obj)obj->MMObjRelease();
		obj = p.obj;
		if(obj)obj->MMObjAddRef();
		return *this;
	};

	//Access as a reference
	inline t& operator *() const
	{
		assert(obj!=0 && "Tried to * on a NULL smart pointer");
		return *obj;
	}
	//Access as a pointer
	inline t* operator ->() const
	{
		assert(obj!=0 && "Tried to -> on a NULL smart pointer");
		return obj;
	}

	// Conversion - allow the smart pointer to be automatically converted to type t*
	inline operator t*() const {
		return obj;
	}
	inline bool isValid() const {
		return (obj!=0);
	}
	inline bool operator!() {
		return !(obj);
	}
	inline bool operator == (const MMPtr<t>&p) const {
		return obj==p.obj;
	}
	inline bool operator == (const t* o) const {
		return (obj==o);
	}
};

#endif